package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func DoubleSlice(slice []int) {
	for key, val := range slice {
		slice[key] = val * 2
	}
}

func RefSlice(slice *[]int) []int {
	*slice = append(*slice, 1)
	return *slice
}

func NonRefSlice(slice []int) []int {
	slice = append(slice, 1)
	return slice
}

func Same(a1 []int, a2 []int) bool {
	head1 := (*reflect.SliceHeader)(unsafe.Pointer(&a1))
	head2 := (*reflect.SliceHeader)(unsafe.Pointer(&a2))
	return *head1 == *head2
}

func main() {
	array := [5]int{1, 2, 3, 4, 5}
	slice := array[:]
	for _, val := range slice {
		fmt.Printf("%d ", val)
	}
	fmt.Println()
	for _, val := range array {
		fmt.Printf("%d ", val)
	}
	fmt.Println()
	slice2 := make([]int, 5, 10)
	for _, val := range slice2 {
		fmt.Printf("%d ", val)
	}
	fmt.Println()

	fmt.Printf("length:%d, capacity:%d\n", len(slice2), cap(slice2))

	slice3 := append(slice2, slice...)
	for _, val := range slice2 {
		fmt.Printf("%d ", val)
	}
	fmt.Println()
	for _, val := range slice3 {
		fmt.Printf("%d ", val)
	}
	fmt.Println()

	copy(slice2, slice)
	for _, val := range slice2 {
		fmt.Printf("%d ", val)
	}
	fmt.Println()

	DoubleSlice(slice)
	for _, val := range slice {
		fmt.Printf("%d ", val)
	}
	fmt.Println()

	slice4 := make([]int, 1, 1)
	slice5 := make([]int, 1, 1)
	slice6 := make([]int, 1, 10)

	fmt.Println(slice4, len(slice4), cap(slice4))
	fmt.Println(NonRefSlice(slice4), slice4, len(slice4), cap(slice4))
	fmt.Println(slice5, len(slice5), cap(slice5))
	fmt.Println(RefSlice(&slice5), slice5, len(slice5), cap(slice5))
	fmt.Println(slice6, len(slice6), cap(slice6))
	fmt.Println(RefSlice(&slice6), slice6, len(slice6), cap(slice6))

	{
		fmt.Println("------------------")
		slice1 := make([]int, 0, 10)
		slice2 = slice1
		fmt.Println(Same(slice1, slice2))
		slice1 = append(slice1, 2)
		fmt.Println(slice1, slice2)
		slice2 = append(slice2, 3)
		fmt.Println(slice1, slice2)
		fmt.Println(Same(slice1, slice2))
	}

	{
		fmt.Println("------------------")
		slice1 := make([]int, 0)
		slice2 = slice1
		fmt.Println(Same(slice1, slice2))
		slice1 = append(slice1, 2)
		fmt.Println(slice1, slice2)
		slice2 = append(slice2, 3)
		fmt.Println(slice1, slice2)
		fmt.Println(Same(slice1, slice2))
	}

	{
		fmt.Println("------------------")
		// index: value
		slice := []int{2: 5, 6, 0: 7}
		fmt.Println(slice)
	}
}
